Dockerfileとタスク定義の変更を既存のFargateに自動デプロイするGithub Actionsを設定した
こちらの記事を参考にタスク定義が更新される度に既存環境の Fargate へ自動デプロイをする Github Actions を設定したので手順を書き残しておくことにしました。
参考: GitHub Actions からサクッと Fargate にデプロイしてみた
ケースシナリオ
Dockerfile とタスク定義ファイルが変更され、レポジトリに Push される度に以下のプロセスを自動実行する Github Actions を設定します。その際に任意の環境へ Assume Role しデプロイできるように設定します。
- AWS 環境へ Assume Role する
- Docker イメージをビルドして既存の ECR へ Push する
- 新しい Image ID でタスク定義を更新する
- ECSクラスタにタスクをデプロイする
環境構成図
今回設定するのはこのあたりです。
Dockerfile
テスト用に Apache httpd のコンテナイメージを指定した Dockerfile を作成しました。 既存環境には nginx のサンプルイメージが上がっているので、httpd に変更します。
FROM httpd
Role の設定
Assume Role したい環境で IAM Role を作成し、必要な権限を渡します。 Role の ARN を 後述の Github Actions に渡します。
Github Actions
.github/workflows/
ディレクトリ下にyml
ファイルを作成し Actions の定義を書いてゆきます。
AWS_ACCESS_KEY_ID
とAWS_SECRET_ACCESS_KEY
はGithub の Secret にあらかじめ登録しておきます。
on: push: branches: - master name: Deploy to Amazon ECS jobs: deploy: name: Deploy runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v1 - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-northeast-1 role-to-assume: <ROLE_ARN> role-duration-seconds: 1200 role-session-name: cdk-assume-role - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v1 - name: Build, tag, and push image to Amazon ECR id: build-image env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} ECR_REPOSITORY: sample-repo IMAGE_TAG: ${{ github.sha }} run: | # Build a docker container and # push it to ECR so that it can # be deployed to ECS. docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" - name: Fill in the new image ID in the Amazon ECS task definition id: task-def uses: aws-actions/amazon-ecs-render-task-definition@v1 with: task-definition: task-definition.json container-name: web image: ${{ steps.build-image.outputs.image }} - name: Deploy Amazon ECS task definition uses: aws-actions/amazon-ecs-deploy-task-definition@v1 with: task-definition: ${{ steps.task-def.outputs.task-definition }} service: <YOUR_SERVICE_NAME> cluster: <YOUR_CLUSTER_NAME> wait-for-service-stability: true
タスク定義
タスク定義ファイルを作成します。既存の環境にデプロイする場合、必要な Role やタスク定義の名前などが必要です。既存のタスク定義の JSON を覗くと何を書けばいいのかだいたいわかるので参考にしてください。
task-definition.json:
{ "executionRoleArn": "<TASK_EXECUTION_IAM_ROLE>", "containerDefinitions": [ { "portMappings": [ { "hostPort": 80, "protocol": "tcp", "containerPort": 80 } ], "image": "hoge", "name": "web" } ], "placementConstraints": [], "memory": "1024", "taskRoleArn": "<TASK_ROLE>", "family": "<TASK_DEFINITION_NAME>", "requiresCompatibilities": ["FARGATE"], "networkMode": "awsvpc", "cpu": "512", "revision": 1, "status": "ACTIVE" }
既存環境の確認
新しいイメージをデプロイする前に既存の環境を確認します。
ALB から確認すると、既存環境にはnginx
のコンテナがデプロイされています。
これがhttpd
に変われば成功です。
実行してみる
レポジトリへ Push してみましょう。 この時点でのファイル構成はこうなっています。
├── .github │ └── workflows │ └── aws.yml ├── Dockerfile ├── README.md └── task-definition.json
タスク定義を更新すると、新しいものを立てて既存のコンテナインスタンスを削除するため、少し時間がかかります。インスタンス内に実行中のタスクがある場合は終了するまで待ってからコンテナインスタンスは停止します。
GUI で ECS のクラスタを確認して見ると、通常は2つのコンテナインスタンスが入れ替えの時は4つ動いていることがわかります。
更新が無事に終わるとインスタンスはまた2つに戻ります。
Github の Actions タブから Actions のステータスが確認できますが、このように全て正常終了すれば完了です。
動作確認
ALB からイメージを確認してみましょう。
このように httpd
のイメージに差し代わっていれば成功です。